package xyz.erupt.flow.core.engine.delegate;

import com.alibaba.fastjson.JSON;
import org.camunda.bpm.engine.delegate.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import xyz.erupt.flow.bean.entity.node.OaProcessNodeAssign;
import xyz.erupt.flow.bean.entity.node.OaProcessNodeLeaderTop;
import xyz.erupt.flow.bean.entity.node.OaProcessNodeProps;
import xyz.erupt.flow.constant.FlowConstant;
import xyz.erupt.flow.repository.EruptPostRepository;
import xyz.erupt.flow.repository.EruptUserRepository;
import xyz.erupt.upms.model.EruptOrg;
import xyz.erupt.upms.model.EruptUser;

import java.util.*;

/**
 * 用户任务监听器（审批人、抄送人用户配置）
 */
@Service("UserTaskDelegate")
public class UserTaskDelegate implements JavaDelegate {
    private Expression props;

    @Autowired
    private EruptUserRepository eruptUserRepository;

    @Override
    public void execute(DelegateExecution execution) throws Exception {
        OaProcessNodeProps propsValue = JSON.parseObject((String) props.getValue(execution), OaProcessNodeProps.class);//获取数据
        //开始分配任务用户，使用流程变量和任务监听器
        buildUserList(execution,propsValue);//构建用户
    }

    private void buildUserList(DelegateExecution execution, OaProcessNodeProps propsValue) {
        ArrayList<String> userList = new ArrayList<>();//用户列表
        Map<String,Object> map = new HashMap<>();//注入变量列表
        //判断条件
        switch (propsValue.getAssignedType()){
            case FlowConstant.ASSIGN_TYPE_USER:{//指定人员
                buildAssignUser(propsValue,userList);//用户名
                break;
            }
            case FlowConstant.ASSIGN_TYPE_ROLE://指定角色
            {
                buildAssignRole(propsValue,userList);//角色编码
                break;
            }
            case FlowConstant.ASSIGN_TYPE_SELF:{//发起人自己
                buildSelfUser(execution,userList);
                break;
            }
            case FlowConstant.ASSIGN_TYPE_FORM_USER:{//表单内联系人
                buildFormUser(propsValue,execution,userList);/**************************************后续考虑实现,和表单传递方式等相关****/
                break;
            }
            case FlowConstant.ASSIGN_TYPE_LEADER:{//主管
                buildLeaderUser(propsValue,execution,userList);
                break;
            }
            case FlowConstant.ASSIGN_TYPE_LEADER_TOP:{//连续多级主管
                buildLeaderTop(propsValue,execution,userList);
                break;
            }
            default:{
                break;
            }

        }

        //注入变量
        map.put("userList",userList);
        execution.setVariables(map);
    }

    /**
     * 连续多级主管
     * @param propsValue
     * @param execution
     * @param userList
     */
    private void buildLeaderTop(OaProcessNodeProps propsValue, DelegateExecution execution, ArrayList<String> userList) {
        OaProcessNodeLeaderTop leaderTop = propsValue.getLeaderTop();
        if(leaderTop!=null){
            Object startUser = execution.getVariable("startUser");
            if(startUser!=null&&!startUser.toString().isEmpty()) {
                EruptUser user = eruptUserRepository.findByAccount(startUser.toString());
                EruptOrg eruptOrg = user.getEruptOrg();
                int i = 0;
                if ("TOP".equals(leaderTop.getEndCondition())){//直到最上层
                    do {
                        if (i>0){
                            eruptOrg=eruptOrg.getParentOrg();
                        }
                        if (eruptOrg!=null){
                            List<EruptUser> users = eruptUserRepository.findTopPostUserByOrgId(eruptOrg.getId());
                            users.forEach(s->{
                                userList.add(s.getAccount());
                            });
                        }
                        i++;
                    }while (eruptOrg.getParentOrg()!=null);
                }else {//不超过发起人的第n级主管（1代表本组织内主管，2包含上层组织内的主管）
                    do {
                        if (i>0){
                            eruptOrg=eruptOrg.getParentOrg();
                        }
                        if (eruptOrg!=null){//连续添加主管
                            List<EruptUser> users = eruptUserRepository.findTopPostUserByOrgId(eruptOrg.getId());
                            users.forEach(s->{
                                userList.add(s.getAccount());
                            });
                        }
                        i++;
                    }while (i<leaderTop.getLevel());
                }
            }
        }
    }

    /**
     * 主管(用戶名)
     * @param propsValue
     * @param execution
     * @param userList
     */
    private void buildLeaderUser(OaProcessNodeProps propsValue, DelegateExecution execution, ArrayList<String> userList) {
        Object startUser = execution.getVariable("startUser");
        if(startUser!=null&&!startUser.toString().isEmpty()){
            EruptUser user = eruptUserRepository.findByAccount(startUser.toString());
            EruptOrg eruptOrg = user.getEruptOrg();
            //循环查找父级主管（1为本组织，2为上级组织，依次类推）
            int i = 0;
            do {
                if (i>0){
                    eruptOrg = eruptOrg.getParentOrg();
                }
                i++;
            }while(i<propsValue.getLeaderTop().getLevel());
            if(eruptOrg!=null){
                //查找该组织最高主管
                List<EruptUser> topPostUserByOrgId = eruptUserRepository.findTopPostUserByOrgId(eruptOrg.getId());
                if(topPostUserByOrgId!=null&&!topPostUserByOrgId.isEmpty()){
                    topPostUserByOrgId.forEach(s->{
                        userList.add(s.getAccount());
                    });
                }
            }
        }
    }

    /****************************************暂未实现
     * 使用表单中选择(用户名)
     * @param propsValue
     * @param userList
     */
    private void buildFormUser(OaProcessNodeProps propsValue,DelegateExecution execution, ArrayList<String> userList) {
        String formUser = propsValue.getFormUser();//表单id
//        formService.getTaskFormVariables()
//        formService.getTaskFormData(execution.getCurrentActivityId())

    }

    /**
     * 设置发起人自己作为任务人(用户名)
     * @param execution
     * @param userList
     */
    private void buildSelfUser(DelegateExecution execution, ArrayList<String> userList) {
        Object startUser = execution.getVariable("startUser");//用户名
        if(startUser!=null&&!startUser.toString().isEmpty()){
            userList.add(startUser.toString());
        }
    }

    /**
     * 指定角色(将角色包含人员找出并全部注入候选人)(角色编码)
     * @param propsValue
     * @param userList
     */
    private void buildAssignRole(OaProcessNodeProps propsValue, ArrayList<String> userList) {
        List<OaProcessNodeAssign> role = propsValue.getRole();
        if(role!=null&&!role.isEmpty()){
            for(OaProcessNodeAssign assign : role){
                userList.add(assign.getId());//角色编码
            }
        }
    }

    /**
     * 指定人员(用户名)
     * @param userList
     */
    private void buildAssignUser(OaProcessNodeProps props,ArrayList<String> userList) {
        List<OaProcessNodeAssign> assignedUser = props.getAssignedUser();
        if(assignedUser!=null && !assignedUser.isEmpty()){
            for (OaProcessNodeAssign oaProcessNodeAssign : assignedUser) {
                userList.add(oaProcessNodeAssign.getId());//用户名
            }
        }
    }

}
